`include "defines.v"
/* verilator lint_off LITENDIAN */
module btb(
  input clk,
  input rst_n,
  // 查询路径
  input [`VADDR_W-1:0]gen_btb_pc_i,
  output hit_o,
  output [`VADDR_W-1:0]predict_pc_o,
  // 更新路径
  input ex_btb_valid_i,
  input ex_btb_branch_i,
  input [`VADDR_W-1:0]ex_btb_pc_i,
  input [`VADDR_W-1:0]ex_btb_jump_pc_i
);
//1valid 32pc 32jumpaddr
reg                btbV    [0:31];
reg [`VADDR_W-1:0] btbTag  [0:31];
reg [`VADDR_W-1:0] btbJAd  [0:31];  

/* 查询路径 */
wire [0:31] hit_vectotr;
genvar i;
generate
  for(i=0;i<32;i=i+1)begin
    assign hit_vectotr[i] = btbV[i] && (btbTag[i] == gen_btb_pc_i) ;
  end
endgenerate
assign hit_o = | hit_vectotr ;
assign predict_pc_o = ({`VADDR_W{hit_vectotr[ 0]}} & btbJAd[ 0]) | 
                      ({`VADDR_W{hit_vectotr[ 1]}} & btbJAd[ 1]) | 
                      ({`VADDR_W{hit_vectotr[ 2]}} & btbJAd[ 2]) | 
                      ({`VADDR_W{hit_vectotr[ 3]}} & btbJAd[ 3]) | 
                      ({`VADDR_W{hit_vectotr[ 4]}} & btbJAd[ 4]) | 
                      ({`VADDR_W{hit_vectotr[ 5]}} & btbJAd[ 5]) | 
                      ({`VADDR_W{hit_vectotr[ 6]}} & btbJAd[ 6]) | 
                      ({`VADDR_W{hit_vectotr[ 7]}} & btbJAd[ 7]) | 
                      ({`VADDR_W{hit_vectotr[ 8]}} & btbJAd[ 8]) | 
                      ({`VADDR_W{hit_vectotr[ 9]}} & btbJAd[ 9]) | 
                      ({`VADDR_W{hit_vectotr[10]}} & btbJAd[10]) | 
                      ({`VADDR_W{hit_vectotr[11]}} & btbJAd[11]) | 
                      ({`VADDR_W{hit_vectotr[12]}} & btbJAd[12]) | 
                      ({`VADDR_W{hit_vectotr[13]}} & btbJAd[13]) | 
                      ({`VADDR_W{hit_vectotr[14]}} & btbJAd[14]) | 
                      ({`VADDR_W{hit_vectotr[15]}} & btbJAd[15]) | 
                      ({`VADDR_W{hit_vectotr[16]}} & btbJAd[16]) | 
                      ({`VADDR_W{hit_vectotr[17]}} & btbJAd[17]) | 
                      ({`VADDR_W{hit_vectotr[18]}} & btbJAd[18]) | 
                      ({`VADDR_W{hit_vectotr[19]}} & btbJAd[19]) | 
                      ({`VADDR_W{hit_vectotr[20]}} & btbJAd[20]) | 
                      ({`VADDR_W{hit_vectotr[21]}} & btbJAd[21]) | 
                      ({`VADDR_W{hit_vectotr[22]}} & btbJAd[22]) | 
                      ({`VADDR_W{hit_vectotr[23]}} & btbJAd[23]) | 
                      ({`VADDR_W{hit_vectotr[24]}} & btbJAd[24]) | 
                      ({`VADDR_W{hit_vectotr[25]}} & btbJAd[25]) | 
                      ({`VADDR_W{hit_vectotr[26]}} & btbJAd[26]) | 
                      ({`VADDR_W{hit_vectotr[27]}} & btbJAd[27]) | 
                      ({`VADDR_W{hit_vectotr[28]}} & btbJAd[28]) | 
                      ({`VADDR_W{hit_vectotr[29]}} & btbJAd[29]) | 
                      ({`VADDR_W{hit_vectotr[30]}} & btbJAd[30]) | 
                      ({`VADDR_W{hit_vectotr[31]}} & btbJAd[31]) ;

/* 更新路径 */
// 找出空闲项
wire [0:31] notValid;
generate
  for(i=0;i<32;i=i+1)begin
    assign notValid[i] = ~btbV[i];
  end
endgenerate

// LFSR 
reg [31:0] lfsr;
always@(posedge clk or negedge rst_n)
  if(~rst_n)
    lfsr <= 32'h89AB_CDEF;
  else 
    lfsr <= {lfsr[30:0],lfsr[31]};

wire [0:31] dec_way = |notValid ? notValid : lfsr;

// 选出一路 有优先级
reg [5:0] replace_way;
always@(*)begin
  replace_way = 5'd0;
  if(dec_way[ 0]) replace_way = 5'd 0;
  if(dec_way[ 1]) replace_way = 5'd 1;
  if(dec_way[ 2]) replace_way = 5'd 2;
  if(dec_way[ 3]) replace_way = 5'd 3;
  if(dec_way[ 4]) replace_way = 5'd 4;
  if(dec_way[ 5]) replace_way = 5'd 5;
  if(dec_way[ 6]) replace_way = 5'd 6;
  if(dec_way[ 7]) replace_way = 5'd 7;
  if(dec_way[ 8]) replace_way = 5'd 8;
  if(dec_way[ 9]) replace_way = 5'd 9;
  if(dec_way[10]) replace_way = 5'd10;
  if(dec_way[11]) replace_way = 5'd11;
  if(dec_way[12]) replace_way = 5'd12;
  if(dec_way[13]) replace_way = 5'd13;
  if(dec_way[14]) replace_way = 5'd14;
  if(dec_way[15]) replace_way = 5'd15;
  if(dec_way[16]) replace_way = 5'd16;
  if(dec_way[17]) replace_way = 5'd17;
  if(dec_way[18]) replace_way = 5'd18;
  if(dec_way[19]) replace_way = 5'd19;
  if(dec_way[20]) replace_way = 5'd20;
  if(dec_way[21]) replace_way = 5'd21;
  if(dec_way[22]) replace_way = 5'd22;
  if(dec_way[23]) replace_way = 5'd23;
  if(dec_way[24]) replace_way = 5'd24;
  if(dec_way[25]) replace_way = 5'd25;
  if(dec_way[26]) replace_way = 5'd26;
  if(dec_way[27]) replace_way = 5'd27;
  if(dec_way[28]) replace_way = 5'd28;
  if(dec_way[29]) replace_way = 5'd29;
  if(dec_way[30]) replace_way = 5'd30;
  if(dec_way[31]) replace_way = 5'd31;
end
wire btb_wen = ex_btb_valid_i && ex_btb_branch_i;
generate
  for(i=0;i<32;i=i+1)begin
    always@(posedge clk ) 
      if(btb_wen && replace_way == i)begin
        btbTag[i] <= ex_btb_pc_i;
        btbJAd[i] <= ex_btb_jump_pc_i;
    end
    always@(posedge clk or negedge rst_n)
      if(~rst_n)
        btbV[i] <= `ZERO;
      else if(btb_wen && replace_way == i )
        btbV[i] <= 1'b1;
  end
endgenerate
endmodule 